package com.train.redis.core.support;

import com.train.common.utils.string.FormatterUtils;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedissonSupport {

    @Autowired
    private RedissonClient redissonClient;

    public RedissonClient getRedissonClient() {
        return redissonClient;
    }

    /**
     * 获取分布式锁
     * @param format
     * @param lockKeys
     * @return
     */
    public RLock getLock(String format, Object... lockKeys) {
        return redissonClient.getLock(FormatterUtils.format(format, lockKeys));
    }

    /**
     * 获取分布式读写锁
     * @param format
     * @param lockKeys
     * @return
     */
    public RReadWriteLock getReadWriteLock(String format, Object... lockKeys) {
        return redissonClient.getReadWriteLock(FormatterUtils.format(format, lockKeys));
    }

    /**
     * 带看门狗加锁
     * @param format
     * @param lockKey
     * @param awaitTime
     * @param timeUnit
     * @return
     */
    public boolean lock(String format, Object[] lockKey, Long awaitTime, TimeUnit timeUnit) {
        return lock(FormatterUtils.format(format, lockKey), awaitTime, timeUnit);
    }

    /**
     * 带看门狗加锁
     * @param lockKey 加锁的key
     * @param awaitTime 线程等待获取锁的时间
     * @param timeUnit 时间单位
     */
    public boolean lock(String lockKey, Long awaitTime, TimeUnit timeUnit) {
        try {
            return redissonClient.getLock(lockKey).tryLock(awaitTime, timeUnit);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 不带看门狗加锁
     * @param format
     * @param lockKey
     * @param awaitTime
     * @param expireTime
     * @param timeUnit
     * @return
     */
    public boolean lock(String format, Object[] lockKey, Long awaitTime, Long expireTime, TimeUnit timeUnit) {
        return lock(FormatterUtils.format(format, lockKey), awaitTime, expireTime, timeUnit);
    }

    /**
     * 不带看门狗加锁
     * @param lockKey 加锁的key
     * @param awaitTime 线程等待获取锁的时间
     * @param expireTime 锁过期时间
     * @param timeUnit 时间单位
     * @return
     */
    public boolean lock(String lockKey, Long awaitTime, Long expireTime, TimeUnit timeUnit) {
        try {
            return redissonClient.getLock(lockKey).tryLock(awaitTime, expireTime, timeUnit);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 当lock不为空和持有lock的线程是当前线程的时候就释放锁
     * @param lock
     */
    public void unlock(RLock lock) {
        if (lock != null && lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}
